package com.my.socket.bio.v3;

import com.my.socket.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by ZhongGang
 * at 2018/6/27 9:47
 */
public class ReverseServer {
    private static final Logger LOGGER = LoggerFactory.getLogger(ReverseServer.class);

    public static void main(String[] args) throws Exception {
        AtomicInteger count = new AtomicInteger(0);

        int nThreads = Runtime.getRuntime().availableProcessors() * 2;
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);

        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress("127.0.0.1", 9999), Integer.MAX_VALUE);
        Socket socket;
        List<Future> futures = new ArrayList<>();
        while ((socket = serverSocket.accept()) != null) {
            Socket finalSocket = socket;
            Future<?> future = executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        try {
                            InputStream inputStream = finalSocket.getInputStream();
                            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                            String line = reader.readLine();
                            LOGGER.info("read line {} from client {}", line, finalSocket);

                            OutputStream outputStream = finalSocket.getOutputStream();
                            PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream));
                            String reversedLine = StringUtils.reverse(line);
                            writer.println(reversedLine);
                            writer.flush();
                            LOGGER.info("write reversed line {} to client {}", reversedLine, finalSocket);
                        } catch (Exception e) {
                            LOGGER.error("exception caught, the error is {}", e.getMessage());
                        } finally {
                            finalSocket.close();
                            LOGGER.info("total connections: {}", count.incrementAndGet());
                        }
                    } catch (Exception e) {
                        LOGGER.error("exception caught, the error is {}", e.getMessage());
                    }
                }
            });
            futures.add(future);
        }

        for (Future future : futures) {
            future.get();
        }
    }
}
